﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
using GxTsSharp;
using GxTsSharp.Models;
using log4net;
using Newtonsoft.Json;
using StockIndex.service;

namespace StockIndex
{
    public class Program
    {
        private static readonly ILog Log = LogManager.GetLogger(typeof(Program));
        public static readonly Eagle Eagle = new Eagle();
        public static bool _isRunning = false;
        public static bool FinsihEagleInit = false;

        public static void Main(string[] args)
        {
            InitConfigData(); //初始化配置文件
            InitEagle();
            //要初始完这些信息才能使用后面的数据
            while (!FinsihEagleInit)
            {
                Thread.Sleep(3000);
                Log.Info("等待初始化");
            }

            TaskConfig.RunTask();
            InitData(); //初始化数据
            Log.Info("初始化完成");
            Eagle.AskMarketPush(0, ConfigData.AMarket);
            var tips = "1:退出\n" +
                       "2:全量补全k线日线数据\n" +
                       "3:同步最近一天k日线数据\n";

            string input;
            do
            {
                input = Console.ReadLine();
                switch (input)
                {
                    case "1":
                        Log.Info("手工退出程序，bye");
                        break;
                    case "2":
                        Log.Info("全量同步k线日数据");
                        TdxDailyKLineService.FullTotalStockDailyKLines();
                        Log.Info("同步全量k线日数据完成");
                        break;
                    case "3":
                        Log.Info("同步最近交易日k线数据");
                        TdxDailyKLineService.FullLastestDailyKLines();
                        Log.Info("同步最近交易日k线数据完成");
                        break;
                    default:
                        Console.Write(tips);
                        break;
                }
            } while (input != "1");


            Destory();
        }

        private static void InitEagle()
        {
            Eagle.OnError += (reqId, code, msg) => { Log.Error($"请求错误|请求ID： {reqId} ，错误代码： {code} ，错误信息： {msg} "); };

            Eagle.OnLoginAsk += (account, version) =>
            {
                _isRunning = true;
                Log.Info($"{account} 已经连接上服务器，版本：{version}");
                Log.Info("开始查询市场状态...");
                var req = Eagle.AskMarketStatus(0, ConfigData.AMarket);
                if (req != 0)
                {
                    Log.Error($"获取市场状态失败|错误码：{req}");
                }
            };

            Eagle.OnMarketStatusAsk += (reqId, status) =>
            {
                var s = status.IsInitial == 1 ? "市场已初始化" : "市场不可用";
                Log.Info($"市场状态：{status.MarketId} {status.Date} {s}");
                if (status.IsInitial == 1)
                {
                    Log.Info("开始查询市场股票信息和排序...");
                    var req = Eagle.AskMarketXmlInitAsk(0, status.MarketId);
                    if (req != 0)
                    {
                        Log.Error($"查询市场股票信息和排序|错误码：{req}");
                    }
                }
            };

            Eagle.OnMarketXmlInit += (reqid, data) =>
            {
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.LoadXml(data);

                var nodeAttribute = xmlDoc.GetElementsByTagName("Attribute")[0];
                if (nodeAttribute.Attributes != null)
                {
                    var id = Convert.ToByte(nodeAttribute.Attributes["ID"].Value);
                    EMarketID marketId = (EMarketID) id;
                    Log.Info($"接收到 {marketId} 市场股票信息和排序");
                    var listXmlStockInfo = xmlDoc.GetElementsByTagName("Stock");
                    var listStockInfo = new List<StockInfo>();
                    for (int i = 0; i < listXmlStockInfo.Count; i++)
                    {
                        var nodeStock = listXmlStockInfo[i];
                        var stockInfo = Eagle.DeserializeObject<StockInfo>(nodeStock);
                        listStockInfo.Add(stockInfo);
                    }

                    Eagle.DicStockInfo.AddOrUpdate(marketId, listStockInfo, (k, v) => listStockInfo);
                    FinsihEagleInit = true;
                }
            };

            //订阅的行情数据返回
            Eagle.OnMarketPush += (marketId, quote, count) =>
            {
                MemoryCacheService.HandleStockReport(Eagle, marketId, count, quote);
            };

            Log.Info("开始初始化 Eagle 行情...");
            var req1 = Eagle.Init();
            if (req1 == 0)
            {
                Log.Info("初始化 Eagle 行情完成");
            }
            else
            {
                Log.Error($"初始化Eagle失败|错误码：{req1}");
            }

            Log.Info("开始登录 Eagle 行情...");
            var req2 = Eagle.NewMultiLogin(ConfigData.Eagle.account, ConfigData.Eagle.name, ConfigData.Eagle.ip,
                ConfigData.Eagle.port);
            if (req2 != 0)
            {
                Log.Error($"登录Eagle失败|错误码：{req2}");
            }
        }


        private static void InitData()
        {
            //初始化主题股票列表
            MainTopicService.FullTopicStocks();

            //初始化市值
            StockMarketService.FullStockMarket();

            //初始化主题权重
            StockMarketService.FullTopicWeight();
            //股票daily数据
            TdxDailyKLineService.FullLastestDailyKLines();
            //上个交易日的各种不同日期涨跌幅
            ZdfService.FullMultiPreviewTopicZdf();
            //计算量比的前置5日平均成交量
            LiangbiService.CalcVolumn();
        }

        private static void InitConfigData()
        {
            var filePath = @"config.json";
            if (!File.Exists(filePath))
            {
                throw new FileNotFoundException();
            }

            var json = File.ReadAllText(filePath);
            ConfigModel config = JsonConvert.DeserializeObject<ConfigModel>(json);

            ConfigData.AMarket = (from x in config.market where x.enabled select x.value).ToArray();
            ConfigData.Eagle = config.eagle;
        }

        public static void Destory()
        {
            TaskConfig.Destroy();
            Log.Info("程序退出结束");
        }
    }
}